#!/user/bin/python
''' This  is raw program for finance_fetion
tolist: 
1. fetion protocol analysis using wireshark
2. porting to web service using oauth
3. more generalized functionality for user'''

import sys
import time
import urllib
from gdata.finance.service import FinanceService, PortfolioQuery, PositionQuery

#SERVER = "http://finance.google.com"
#BASEPATH = "/finance/feeds/"
#BASE_URL = SERVER + BASEPATH + 'default'

# feed and Entry URI suffixes
#PORTFOLIO_FEED_URL_SUFFIX = "/portfolios";
#POSITION_FEED_URL_SUFFIX = "/positions";
#TRANSACTION_FEED_URL_SUFFIX = "/transactions";

STOCK_SHA = "SHA:"
STOCK_SHE = "SHE:"


class StockInfo(object):
	def __init__(self, latest_price, stock_name):
		self.latest_price = latest_price
		self.high_price = {} 
		self.low_price = {}
		self.name = stock_name
	def set_highprice(self, price):
		if not self.high_price.has_key(price):
		    self.high_price[price] = True
	def set_lowprice(self, price):
		if not self.low_price.has_key(price):
		    self.low_price[price] = True

class GFinance(object):
	def __init__(self, gaccount='nightelf1984@gmail.com', gpasswd='jie_night'):
		self.gfinance_service = FinanceService(source='gdata-finance-test')
		self.gfinance_service.ClientLogin(gaccount, gpasswd)
		self.price_listen = {}
		
		#self.dump_info()
		#self.set_watchprice()
		#self.listen()
	
	def get_stock_price(self, code):
		pfl = self.getportfolio('1')
		pos = self.getposition(pfl, code)
		return self.cal_price(pos)
		#self.show_position(postion)
	
	def listen(self):
		while(True):
			self.notify_check()
			time.sleep(2.0) # check per 2 seconds 

	def get_listen_price(self):
		return self.price_listen
	
	def getportfolios(self):
		portfolio_query = PortfolioQuery()
		portfolio_query.returns = False
		portfolio_query.positions = False
		return self.gfinance_service.GetPortfolioFeed(query=portfolio_query).entry

	def getpostions(self, pfl):
		position_query = PositionQuery()
		position_query.returns = True 
		position_query.transactions = False
		return self.gfinance_service.GetPositionFeed(pfl, query=position_query).entry
	
	def getportfolio(self, pfl_id):
		query = PortfolioQuery()
		query.returns = True
		query.positions = False
		return self.gfinance_service.GetPortfolio(portfolio_id=pfl_id, query=query)
	
	def getposition(self, pfl, ticker):
		ticker = self.get_wholeticker(ticker)
		query = PositionQuery()
		query.returns = True
		query.transactions = False
		return self.gfinance_service.GetPosition(
				portfolio_id=pfl.portfolio_id, ticker_id=ticker, query=query)
	
	def dump_info(self):
		portfolios = self.getportfolios()
		for pfl in portfolios:
			self.show_portfolio(pfl)
			positions = self.getpostions(pfl)
			for pos in positions:
				self.show_position(pos)
			
	def show_portfolio(self, pfl):
		"""print sinfle portfolio."""
		print '=====Portfolio ID     :', pfl.portfolio_id, "=" * 50
		print 'Title    :', pfl.portfolio_title
		print 'Last updated     :', pfl.updated.text
	
	def show_position(self, position):
		"""print single stock"""
		print '    Symbol      :', position.symbol
		#print dir(position.symbol)
		print '    Name        :', position.position_title
		price = self.cal_price(position)
		print '    Price       :', price
		self.price_listen[position.symbol.symbol] = StockInfo(price, position.position_title)
	
	def cal_price(self, pos):
		#print type(pos)
		d = pos.position_data
		#print d.ToString()
		#print type(d)
		#print dir(d)
		money = d.market_value.money[0]
		yestday = float(money.amount)
		money = d.days_gain.money[0]
		days_gain = float(money.amount)
		shares = float(d.shares)
		return (days_gain + yestday) / shares
		
	def set_watchprice(self):
		symbols = self.price_listen.keys()
		for symbol in symbols:
			print '=======Corp name is: ', self.price_listen[symbol].name, '='*50
			print '=======The latest price is ', self.price_listen[symbol].latest_price, '='*50
			high_price = raw_input("please input your watch price(high) -> press enter if you don't want to specify: ")
			low_price = raw_input("please input your watch price(low) -> press enter if you don't want to specify: ")
			if not high_price == '':
				self.price_listen[symbol].set_highprice(float(high_price))
			if not low_price == '':
			    self.price_listen[symbol].set_lowprice(float(low_price))
	
	def del_watchprice(self, symbol, index):
		pass
    
	def notify_check(self):
		#stocks = self.price_listen.keys()
		portfolios = self.getportfolios()
		for pfl in portfolios:
			positions = self.getpostions(pfl)
			for pos in positions:
				symbol = pos.symbol
				price = self.cal_price(pos)
				#print price
				self.check_price(price, symbol)
	
	def check_price(self, price, symbol):
		stock_info = self.price_listen[symbol.symbol]
		high_prices = stock_info.high_price.keys()
		low_prices = stock_info.low_price.keys()
		for watch_price in high_prices:
			if price >= watch_price and stock_info.high_price[watch_price]:
				print symbol, 'exceed than high watch price bound and sending fetion notification...'
				message_content = 'current price of %s is %s which is larger than your watch_price %s' %(symbol, price, watch_price)
				self.make_fetion_request(message_content)
				stock_info.high_price[watch_price] = False
				print 'sending fetion notification end...'
			elif price < watch_price and not stock_info.high_price[watch_price]:
				stock_info.high_price[watch_price] = True
			else:
				pass
		for watch_price in low_prices:
			if price <= watch_price and stock_info.low_price[watch_price]:
				print symbol, 'lower than low watch price bound and sending fetion notification...'
				message_content = 'current price of %s is %s which is lower than your watch priice %s' %(symbol, price, watch_price)
				self.make_fetion_request(message_content)
				stock_info.low_price[watch_price] = False
				print 'sending fetion notification end...'
			elif price > watch_price and not stock_info.low_price[watch_price]:
				stock_info.low_price[watch_price] = True


	def get_wholeticker(self, code):
		if code[0] == '6':
			ticker = STOCK_SHA + code
		else:
			ticker = STOCK_SHE + code
		return ticker

if __name__ == '__main__':
	#google_account = raw_input('please input your gmail account: ')
	#google_passwd = raw_input('please input your gmail password: ')
	#fetion_account = raw_input('please input your fetion account, now just phone number: ')
	#fetion_passwd = raw_input('please input your fetion password: ')

	#fetion_account = '13601804916'
	#fetion_account = 'sj19840615'
	
	#fetion_account = '13564444868'
	#fetion_passwd = '308831015ppp'

	#finance_fetion = FinanceFetion(google_account, google_passwd, fetion_account, fetion_passwd)
	#finance_fetion = FinanceFetion('nightelf1984@gmail.com', 'jie_night', fetion_account, fetion_passwd)
	#google_account = 'nightelf1984@gmail.com'
	#google_passwd = 'jie_night'
	gfinance = GFinance()
	print gfinance.get_stock_price('600545')
	
	#finance_fetion.dump_info()
	#finance_fetion.set_watchprice()
	#finance_fetion.listen()
